package com.whut.imservice.factory;

import io.netty.util.concurrent.FastThreadLocal;
import io.netty.util.concurrent.FastThreadLocalThread;
import io.netty.util.internal.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Description: 增强线程工厂类
 * @Author: Zonghe Wang
 * @Date: 2025/5/24 19:49
 */
public class EnhancedThreadFactory implements ThreadFactory {
    private static final Logger log = LoggerFactory.getLogger(EnhancedThreadFactory.class);
    private static final AtomicInteger poolId = new AtomicInteger();

    private final AtomicInteger nextId = new AtomicInteger();
    private final String prefix;
    private final boolean daemon;
    private final int priority;

    // 统一构造方法入口
    public EnhancedThreadFactory(Class<?> poolType) {
        this(poolType, false, Thread.NORM_PRIORITY);
    }

    public EnhancedThreadFactory(String poolName) {
        this(poolName, false, Thread.NORM_PRIORITY);
    }

    public EnhancedThreadFactory(Class<?> poolType, boolean daemon) {
        this(poolType, daemon, Thread.NORM_PRIORITY);
    }

    public EnhancedThreadFactory(String poolName, boolean daemon) {
        this(poolName, daemon, Thread.NORM_PRIORITY);
    }

    public EnhancedThreadFactory(Class<?> poolType, int priority) {
        this(poolType, false, priority);
    }

    public EnhancedThreadFactory(String poolName, int priority) {
        this(poolName, false, priority);
    }

    public EnhancedThreadFactory(Class<?> poolType, boolean daemon, int priority) {
        this(toPoolName(poolType), daemon, priority);
    }

    public EnhancedThreadFactory(String poolName, boolean daemon, int priority) {
        validateParameters(poolName, priority);
        this.prefix = generatePrefix(poolName);
        this.daemon = daemon;
        this.priority = priority;
    }

    @Override
    public Thread newThread(Runnable r) {
        final String threadName = prefix + nextId.incrementAndGet();
        Thread t = newThread(new EnhancedRunnableDecorator(r), threadName);

        configureThread(t);
        return t;
    }

    protected Thread newThread(Runnable r, String name) {
        return new FastThreadLocalThread(r, name);
    }

    private static class EnhancedRunnableDecorator implements Runnable {
        private final Runnable target;
        private final Map<String, String> mdcContext;

        EnhancedRunnableDecorator(Runnable target) {
            this.target = target;
            // 获取当前MDC上下文快照
            this.mdcContext = MDC.getCopyOfContextMap();
        }

        @Override
        public void run() {
            try {
                if (mdcContext != null) {
                    // 还原MDC上下文
                    MDC.setContextMap(mdcContext);
                } else {
                    MDC.clear();
                }
                target.run();
            } finally {
                // 确保清除FastThreadLocal数据
                FastThreadLocal.removeAll();
                // 可选：根据需求决定是否清除MDC
                MDC.clear();
            }
        }
    }

    /**
     * 参数校验集中处理
     * @param poolName
     * @param priority
     */
    private static void validateParameters(String poolName, int priority) {
        if (poolName == null) {
            throw new IllegalArgumentException("poolName不能为空");
        }
        if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
            throw new IllegalArgumentException(
                    "priority不合法: " + priority + " (合法范围为: " + Thread.MIN_PRIORITY + "-" + Thread.MAX_PRIORITY + ")");
        }
    }

    /**
     * 线程名前缀生成
     * @param poolName
     * @return
     */
    private static String generatePrefix(String poolName) {
        return poolName + "-" + poolId.incrementAndGet() + "-";
    }

    /**
     * 将类名转换为线程池名称
     * @param poolType
     * @return
     */
    private static String toPoolName(Class<?> poolType) {
        if (poolType == null) {
            throw new IllegalArgumentException("pollType不能为空");
        }

        String simpleName = StringUtil.simpleClassName(poolType);
        if (simpleName.isEmpty()) {
            return "unknown";
        }

        if (simpleName.length() == 1) {
            return simpleName.toLowerCase(Locale.ROOT);
        }

        char firstChar = simpleName.charAt(0);
        char secondChar = simpleName.charAt(1);
        if (Character.isUpperCase(firstChar) && Character.isLowerCase(secondChar)) {
            return Character.toLowerCase(firstChar) + simpleName.substring(1);
        }
        return simpleName;
    }

    /**
     * 线程配置逻辑封装
     * @param t
     */
    private void configureThread(Thread t) {
        try {
            if (t.isDaemon() != daemon) {
                t.setDaemon(daemon);
            }
            if (t.getPriority() != priority) {
                t.setPriority(priority);
            }
        } catch (SecurityException e) {
            log.warn("配置线程 {} 失败 - 权限不足", t.getName(), e);
        } catch (Exception e) {
            log.warn("配置线程报异常 {}", t.getName(), e);
        }
    }
}
